package jp.sourceforge.akjrcp.text_douga.video;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;

import jp.sourceforge.akjrcp.text_douga.DougaSystem;
import jp.sourceforge.akjrcp.text_douga.VideoData;
import jp.sourceforge.akjrcp.text_douga.VideoWriter;
import jp.sourceforge.akjrcp.util.image.ImageUtils;

import org.apache.commons.io.FileUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import sun.awt.image.ByteArrayImageSource;

public class TextDougaVideoUtils {
	public static Log log=LogFactory.getLog(TextDougaVideoUtils.class);
	//copy jpeg
	//return writed;
	public static int copyVideo(String ffmpegPath,String inputPath,double start,double duration,File exportDir,int startIndex,double fps,int width,int height,int maxframe) throws IOException{
		int writed=0;
		
		VideoImageInput videoInput=new VideoImageInput(ffmpegPath,inputPath,start,duration);
		videoInput.setFps(fps);
		videoInput.setWidth(width);
		videoInput.setHeight(height);
		
		JpegKeeper jpegKeeper=videoInput.getJpegKeeper();
		videoInput.startInput();
		
		byte[] bytes;
		while((bytes=jpegKeeper.nextImage())!=null){
			if(DougaSystem.cancelling){
				log.info("dougasystem cancelled");
				break;
			}
			
			File jpegFile=new File(exportDir,toFileName("",startIndex+writed,5,"jpg"));
			writed++;
			FileUtils.writeByteArrayToFile(jpegFile, bytes);
			log.trace("write:"+writed);
			if(writed==maxframe){
				videoInput.setCanceling(true);
				break;
			}
		}
		
		return writed;
	}
	
	public static int copyVideo(VideoData videoData,VideoWriter writer,String ffmpegPath,String inputPath,double start,double duration,double fps,int width,int height) throws IOException{
		int writed=0;
		
		VideoImageInput videoInput=new VideoImageInput(ffmpegPath,inputPath,start,duration);
		videoInput.setFps(fps);
		videoInput.setWidth(width);
		videoInput.setHeight(height);
		
		JpegKeeper jpegKeeper=videoInput.getJpegKeeper();
		videoInput.startInput();
		
		byte[] bytes=null;
		BufferedImage img=null;
		boolean finished=false;
		while((bytes=jpegKeeper.nextImage())!=null){
			if(DougaSystem.cancelling){
				log.info("dougasystem cancelled");
				break;
			}
			
			//File jpegFile=new File(exportDir,toFileName("",startIndex+writed,5,"jpg"));
			//FileUtils.writeByteArrayToFile(jpegFile, bytes);
			
			//どうして最初に書き出すのかは謎
			if(img!=null){
				finished=writer.writeFrame(videoData, img);
				writed++;
				if(finished){
					videoInput.setCanceling(true);
					break;
				}
			}
			
			img=ImageIO.read(new ByteArrayInputStream(bytes));
			log.trace("write:"+writed);
		}
		
		if(!finished && img!=null){
			writer.writeFrame(videoData, img);
			writed++;
		}
		
		return writed;
	}
	
	public static int copyImage(BufferedImage image,File exportDir,int startIndex,int frames) throws IOException{
		int writed=0;
		
			for(int i=0;i<frames;i++){
				if(DougaSystem.cancelling){
					log.info("dougasystem cancelled");
					break;
				}
			File jpegFile=new File(exportDir,toFileName("",startIndex+writed,5,"jpg"));
			writed++;
			ImageUtils.writeJpegWithQuality(image, jpegFile, 1.0f);
			}
		
		
		return writed;
	}
	
	public static int copyImage(BufferedImage image,VideoData videoData,VideoWriter writer,int frames) throws IOException{
		int writed=0;
		
			for(int i=0;i<frames;i++){
				if(DougaSystem.cancelling){
					log.info("dougasystem cancelled");
					break;
				}
				writer.writeFrame(videoData, image);//TODO care ends.
				writed++;
				if(writed%100==0){
				//this take so much time
				log.info("copyImage writed:"+writed);
				}
			}
		
		
		return writed;
	}
	
	public static int loopVideo(String ffmpegPath,String input,double start,double duration,int looptime,double padtime,int padcolor,boolean cutInLoop,File exportDir,int startIndex,double fps,int width,int height,int maxframe) throws IOException{
		if(looptime==0){
			log.warn("loop is 0");
			return 0;
		}
		if(looptime==DougaSystem.FOREEVER && maxframe==0){
			log.warn("it's never stop");
			return 0;
		}
		log.info("cutInLoop:"+cutInLoop);
		//first loop;
		int firstWrite=copyVideo(ffmpegPath,input,start,duration,exportDir,startIndex,fps,width,height,maxframe);
		if(looptime==1){
			return firstWrite;
		}
		log.info("first write:"+firstWrite);
		//finish max;
		int writed=firstWrite;
		if(writed>=maxframe && maxframe>0){//0 don't care
			return writed;
		}
		
		
		int looped=1;//done already 1 time
		
		
		boolean loop=true;
		LOOP:while(loop){
		
			//pad first
			if(loop && padtime>0){
				int colorframe=(int) (fps*padtime);
				for (int i = 0; i < colorframe; i++) {
					if(DougaSystem.cancelling){
						log.info("dougasystem cancelled");
						break LOOP;
					}
					String colorPath=exportDir.getAbsolutePath()+"\\"+toFileName("",startIndex+writed,5,"jpg");//todo
					writeColorImage(width,height,colorPath,padcolor);
					writed++;
					if(writed==maxframe){//never 0
						break LOOP;//on pad any way break;
					}
				}
				log.info("pad:"+colorframe+" color"+padcolor);
				}
			
		for(int i=0;i<firstWrite;i++){
			//copy
			String srcPath=exportDir.getAbsolutePath()+"\\"+toFileName("", startIndex+i, 5, "jpg");//todo;
			String destPath=exportDir.getAbsolutePath()+"\\"+toFileName("",startIndex+writed,5,"jpg");//todo;
			FileUtils.copyFile(new File(srcPath), new File(destPath));
			//check max?
			writed++;
			if(writed==maxframe){//never 0
				if(cutInLoop){
					break LOOP;
				}else{
					loop=false;
				}
				
			}
		}
		
		looped++;
		if(looped==looptime){
			loop=false;
			}
		

		
		log.info("loop:"+looped+" write"+writed);
		}
		
		return writed;
	}
	

	public static int loopVideo(VideoData videoData,VideoWriter writer,String ffmpegPath,String input,double start,double duration,int looptime,double padtime,int padcolor,boolean cutInLoop,double fps,int width,int height) throws IOException{
		if(looptime==0){
			log.warn("loop is 0");
			return 0;
		}
		if(looptime==DougaSystem.FOREEVER && writer.getMaxFrame()==0){
			log.warn("it's never stop");
			return 0;
		}
		log.info("cutInLoop:"+cutInLoop);
		int startIndex=writer.getWrited()+1;
		int maxframe=Math.max(0, writer.getMaxFrame()-writer.getWrited());
		//first loop;
		int firstWrite=copyVideo(ffmpegPath,input,start,duration,writer.getWorkingDir(),startIndex,fps,width,height,maxframe);
		//
		
		for(int i=0;i<firstWrite;i++){
			File frame=writer.getWorkingFrameFile(i+startIndex);
			BufferedImage image=ImageIO.read(frame);
			writer.writeFrame(videoData, image);
		}
		
		//
		if(looptime==1){
			return firstWrite;
		}
		log.info("first write:"+firstWrite);
		//finish max;
		int writed=firstWrite;
		if(writed>=maxframe && maxframe>0){//0 don't care
			return writed;
		}
		
		
		int looped=1;//done already 1 time
		
		
		boolean loop=true;
		LOOP:while(loop){
		
			//pad first
			if(loop && padtime>0){
				int colorframe=(int) (fps*padtime);
				for (int i = 0; i < colorframe; i++) {
					if(DougaSystem.cancelling){
						log.info("dougasystem cancelled");
						break LOOP;
					}
					BufferedImage colorImage=makeColorImage(width,height,padcolor);
					//writeColorImage(width,height,colorPath,padcolor);
					writer.writeFrame(videoData, colorImage);
					writed++;
					if(writed==maxframe){//never 0
					
						break LOOP;//on pad any way break;
					}
				}
				log.info("pad:"+colorframe+" color"+padcolor);
				}
			
		for(int i=0;i<firstWrite;i++){
			//copy
			//srcPath=exportDir.getAbsolutePath()+"\\"+toFileName("", startIndex+i, 5, "jpg");//todo;
			File frame=writer.getWorkingFrameFile(i+startIndex);
			BufferedImage image=ImageIO.read(frame);
			//String destPath=exportDir.getAbsolutePath()+"\\"+toFileName("",startIndex+writed,5,"jpg");//todo;
			//FileUtils.copyFile(new File(srcPath), new File(destPath));
			//check max?
			writer.writeFrame(videoData, image);
			writed++;
			if(writed==writer.getMaxFrame()){//never 0
				if(cutInLoop){
					break LOOP;
				}else{
					loop=false;
				}
				
			}
		}
		
		looped++;
		if(looped==looptime){
			loop=false;
			}
		

		
		log.info("loop:"+looped+" write"+writed);
		}
		
		return writed;
	}

	public static void writeColorImage(int width,int height,String path,int color) throws IOException{
		ImageIO.write(makeColorImage(width,height,color), "jpeg", new File(path));
	}
	public static BufferedImage makeColorImage(int width,int height,int color){
		BufferedImage bimage=new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
		Graphics g=bimage.getGraphics();
		g.setColor(new Color(color));
		g.fillRect(0, 0, width, height);
		return bimage;
	}
	
	public static String toFileName(String header,int index,int digits,String extension){
		String value=header;
		String c=""+index;
		while(c.length()<digits){
			c="0"+c;
		}
		value+=c;
		value+="."+extension;
		return value;
	}

	//position writing version
	public static int copyVideo(FileVideoData videoData,
			VideoWriter writer, String ffmpegPath, String inputPath,
			double startTime, double duration, double fps, int width,
			int height, int x, int y, int inputWidth, int inputHeight) throws IOException{
//System.out.println(x+","+y+","+inputWidth+","+inputHeight);
int writed=0;
		
		VideoImageInput videoInput=new VideoImageInput(ffmpegPath,inputPath,startTime,duration);
		videoInput.setFps(fps);
		videoInput.setWidth(width);
		videoInput.setHeight(height);
		
		JpegKeeper jpegKeeper=videoInput.getJpegKeeper();
		videoInput.startInput();
		
		byte[] bytes=null;
		BufferedImage img=null;
		boolean finished=false;
		while((bytes=jpegKeeper.nextImage())!=null){
			if(DougaSystem.cancelling){
				log.info("dougasystem cancelled");
				break;
			}
			
			//File jpegFile=new File(exportDir,toFileName("",startIndex+writed,5,"jpg"));
			//FileUtils.writeByteArrayToFile(jpegFile, bytes);
			
			//どうして最初に画像を書き出すのかは謎
			if(img!=null){
				if(inputWidth==0){
					inputWidth=img.getWidth();
				}
				if(inputHeight==0){
					inputHeight=img.getHeight();
				}
				//log.trace("base:"+width+","+height);
				BufferedImage bimage=new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
				Graphics g=bimage.getGraphics();
				g.drawImage(img,x,y,x+inputWidth,y+inputHeight,0,0,img.getWidth(),img.getHeight(),null); 
				//log.trace("base:"+x+","+y+","+inputWidth+","+inputHeight);
				img=null;
				finished=writer.writeFrame(videoData, bimage);
				writed++;
				if(finished){
					videoInput.setCanceling(true);
					break;
				}
			}
			
			img=ImageIO.read(new ByteArrayInputStream(bytes));
			log.trace("write:"+writed);
		}
		
		//あまった画像を書き出し???
		if(!finished && img!=null){
			BufferedImage bimage=new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
			Graphics g=bimage.getGraphics();
			g.drawImage(img,x,y,inputWidth,inputHeight,0,0,img.getWidth(),img.getHeight(),null); 
			img=null;
			writed++;
		}
		
		return writed;
	}
}
